﻿/* 2011/11/18 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Xml;

namespace Cosmos.Shortcuts
{
    /// <summary>
    /// A key code and its control, alter, shift status.
    /// </summary>
    public struct KeyCombination : IShortcutAction
    {
        private Keys _key;
        private bool _control;
        private bool _alter;
        private bool _shift;

        public KeyCombination(Keys key, bool control, bool alter, bool shift)
            : this()
        {
            _key = key;
            _control = control;
            _alter = alter;
            _shift = shift;
        }

        public KeyCombination(Keys key)
            : this(key, false, false, false)
        {

        }

        public KeyCombination(string escapeString)
            : this()
        {
            EscapeString = escapeString;
        }

        /// <summary>
        /// Determines whether this KeyCombination and a specified KeyCombination have the same value.
        /// </summary>
        public bool Equals(KeyCombination value)
        {
            return _key == value._key && _control == value._control 
                && _alter == value._alter && _shift == value._shift;
        }

        private string GenerateEscapeString()
        {
            StringWriter stringWriter = new StringWriter();

            XmlWriter theWriter = XmlWriter.Create(stringWriter, SimpleXmlSettings.WriterSettings);
            theWriter.WriteStartElement("Key");
            theWriter.WriteString(((int)Key).ToString());
            theWriter.WriteEndElement();
            theWriter.WriteStartElement("CombineNumber");
            theWriter.WriteString(CombineNumber.ToString());
            theWriter.WriteEndElement();
            theWriter.Flush();
            theWriter.Close();

            stringWriter.Flush();
            string result = stringWriter.ToString();
            stringWriter.Close();
            return result;
        }

        private void ParseEscapeString(string escapeString)
        {
            StringReader stringReader = new StringReader(escapeString);

            XmlReader theReader = XmlReader.Create(stringReader, SimpleXmlSettings.ReaderSettings);
            theReader.ReadStartElement("Key");
            Key = (Keys)theReader.ReadContentAsInt();
            theReader.ReadEndElement();
            theReader.ReadStartElement("CombineNumber");
            CombineNumber = theReader.ReadContentAsInt();
            theReader.ReadEndElement();
            theReader.Close();

            stringReader.Close();
        }

        public string EscapeString
        {
            get { return GenerateEscapeString(); }
            set { ParseEscapeString(value); }
        }

        public Keys Key { get { return _key; } set { _key = value; } }
        public bool Control { get { return _control; } set { _control = value; } }
        public bool Alter { get { return _alter; } set { _alter = value; } }
        public bool Shift { get { return _shift; } set { _shift = value; } }
        public int CombineNumber
        {
            get
            {
                int result = 0x0;
                if (Control) result |= 0x1;
                if (Alter) result |= 0x2;
                if (Shift) result |= 0x4;
                return result;
            }
            set
            {
                Control = ((value & 0x1) == 0x1);
                Alter = ((value & 0x2) == 0x2);
                Shift = ((value & 0x4) == 0x4);
            }
        }
    }

    /// <summary>
    /// A key code and its information.
    /// </summary>
    public class KeyInformation
    {
        private Keys _key;
        private string _description;

        public KeyInformation(Keys key, string description)
        {
            _key = key;
            _description = description;
        }

        public KeyInformation(Keys key)
            : this(key, null)
        {

        }

        public Keys Key { get { return _key; } }
        public string Description { get { return _description; } }
    }

    /// <summary>
    /// Collection of KeyInformation instances.
    /// </summary>
    public class KeyInformationCollection : IEnumerable<KeyInformation>
    {
        private KeyInformation[] _keys;

        public KeyInformationCollection(params KeyInformation[] keys)
        {
            _keys = keys;
        }

        public IEnumerator<KeyInformation> GetEnumerator()
        {
            for (int i = 0; i < _keys.Length; i++)
                yield return _keys[i];
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
